package gov.fgn.sijyp.general.util;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.richfaces.component.SortOrder;
import org.richfaces.component.UIDataScroller;
import org.richfaces.component.UIDataTable;

import com.google.common.collect.Maps;

public abstract class TableBean {

  protected Map<String, SortOrder> sortOrders = Maps.newHashMapWithExpectedSize(1);
  protected Map<String, Object> filterValues = Maps.newHashMap();
  protected String sortProperty;
  protected String messageCurrentRecords;
  /**
   * Índice del primer valor a partir del cual se hará la consulta
   */
  protected Integer firstRecordIndex;

  /**
   * Cantidad total de registros
   */
  protected Integer totalRecords;

  /**
   * Número de registros por página
   */
  protected Integer pageSize;

  private UIDataTable UITabla;

  protected UIDataScroller dataScroller;

  /**
   * Para utilizar la tala ordenable, filtrable y paginable debe
   * implemenarse una subclase de DataModel.
   */
  public abstract Object getDataModel();

  /**
   * Método utilizado para alternar el valor de ordenamiento de una
   * columna, modifica el valor de ordenamiento de la propiedad
   * "sortProperty" de ordenamiento
   * 
   * @link getSortProperty
   */
  public void toggleSort() {
    for (Entry<String, SortOrder> entry : sortOrders.entrySet()) {
      SortOrder newOrder;

      if (entry.getKey().equals(sortProperty)) {
        if (entry.getValue() == SortOrder.ascending) {
          newOrder = SortOrder.descending;
        }
        else {
          newOrder = SortOrder.ascending;
        }
      }
      else {
        newOrder = SortOrder.unsorted;
      }

      entry.setValue(newOrder);
    }
  }

  /**
   * Inicialización del mapa de valores de ordenamiento de columnas
   */
  public void populateSortOrders(List<?> enumValues) {
    for (int i = 0; i < enumValues.size(); i++) {
      this.sortOrders.put(enumValues.get(i).toString(), SortOrder.unsorted);
    }
  }

  /**
   * Método que ensambla el mensaje requerido para indicar los
   * registros en la acutal vista de la tabla. Por ejemplo: 10 a 20 de
   * 54 Registros
   * 
   * @author fabio.navarrete
   */
  public void joinCurrentRecordsMessage() {

    this.pageSize = 10;
    this.totalRecords = this.dataScroller.getRowCount();
    if (this.totalRecords > 0) {
      this.firstRecordIndex = this.pageSize * (this.dataScroller.getPage() - 1) + 1;
    }
    else {
      this.firstRecordIndex = 0;
    }
    if (this.firstRecordIndex != null && this.pageSize != null && this.totalRecords != null) {

      StringBuffer sb = new StringBuffer();
      sb.append(ManagedBeanUtils.getMessagesBundle().getString("general.tabla.recordsMessage"));
      sb.append(" ");
      sb.append(this.firstRecordIndex);
      sb.append(" ");
      sb.append(ManagedBeanUtils.getMessagesBundle()
                                .getString("general.tabla.firstJoinRecordsMessage"));
      sb.append(" ");
      if (this.firstRecordIndex + this.pageSize >= this.totalRecords) {
        sb.append(this.totalRecords);
      }
      else {
        sb.append(this.firstRecordIndex + this.pageSize - 1);
      }
      sb.append(" ");
      sb.append(ManagedBeanUtils.getMessagesBundle()
                                .getString("general.tabla.secondJoinRecordsMessage"));
      sb.append(" ");
      sb.append(this.totalRecords);
      this.setMessageCurrentRecords(sb.toString());
    }
    /*
     * if (this.firstRecordIndex != null && this.pageSize != null &&
     * this.totalRecords != null) { StringBuffer sb = new
     * StringBuffer();
     * sb.append(ManagedBeanUtils.getMessagesBundle().getString
     * ("general.tabla.recordsMessage")); sb.append(" ");
     * sb.append(this.firstRecordIndex); sb.append(" ");
     * sb.append(ManagedBeanUtils.getMessagesBundle()
     * .getString("general.tabla.firstJoinRecordsMessage"));
     * sb.append(" "); if (this.firstRecordIndex + this.pageSize >=
     * this.totalRecords) { sb.append(this.totalRecords); } else {
     * sb.append(this.firstRecordIndex + this.pageSize); }
     * sb.append(" "); sb.append(ManagedBeanUtils.getMessagesBundle()
     * .getString("general.tabla.secondJoinRecordsMessage"));
     * sb.append(" "); sb.append(this.totalRecords);
     * this.setMessageCurrentRecords(sb.toString()); }
     */
  }

  /**
   * Getter del mapa de valores de ordenación, que contiene los
   * valores por los que se deben ordenar los registros de la tabla
   */
  public Map<String, SortOrder> getSortOrders() {
    return sortOrders;
  }

  /**
   * Setter del mapa de valores de ordenación
   */
  public void setSortOrders(Map<String, SortOrder> sortOrders) {
    this.sortOrders = sortOrders;
  }

  /**
   * Getter del mapa de valores del filtro, que contiene los valores
   * de filtro de resultados a mostrar en la tabla
   **/
  public Map<String, Object> getFilterValues() {
    return filterValues;
  }

  /**
   * Setter del mapa de valores del filtro
   */
  public void setFilterValues(Map<String, Object> filterValues) {
    this.filterValues = filterValues;
  }

  /**
   * Getter de sort property, propiedad sobre la que se alterna el
   * valor de ordenamiento
   */
  public String getSortProperty() {
    return sortProperty;
  }

  /**
   * Setter de SortProperty
   */
  public void setSortProperty(String sortProperty) {
    this.sortProperty = sortProperty;
  }

  public String getMessageCurrentRecords() {
    this.joinCurrentRecordsMessage();
    return messageCurrentRecords;
  }

  public void setMessageCurrentRecords(String messageCurrentRecords) {
    this.messageCurrentRecords = messageCurrentRecords;
  }

  public Integer getFirstRecordIndex() {
    return firstRecordIndex;
  }

  public void setFirstRecordIndex(Integer firstRecordIndex) {
    this.firstRecordIndex = firstRecordIndex;
  }

  public Integer getTotalRecords() {
    return totalRecords;
  }

  public void setTotalRecords(Integer totalRecords) {
    this.totalRecords = totalRecords;
  }

  public Integer getPageSize() {
    return pageSize;
  }

  public void setPageSize(Integer pageSize) {
    this.pageSize = pageSize;
  }

  /**
   * Sirve para relacionar el componente de apariencia con el backing
   * bean para funcionaldades adicionales como estado de paginación.
   */
  public UIDataTable getTablaUI() {
    return UITabla;
  }

  public void setTablaUI(UIDataTable dataUi) {
    UITabla = dataUi;

  }

  /**
   * @return the dataScroller
   */
  public UIDataScroller getDataScroller() {
    return dataScroller;
  }

  /**
   * @param dataScroller
   *          the dataScroller to set
   */
  public void setDataScroller(UIDataScroller dataScroller) {
    this.dataScroller = dataScroller;
  }
}
